package com.corpgovernment.common.utils;

import java.util.Arrays;
import java.util.Objects;
import java.util.function.Function;

@SuppressWarnings("WeakerAccess")
public final class Null {

    /**
     * 当expect为null，返回replace, 等价于.net的 expect ?? replace
     * demo : Null.or(expect, replace);
     */
    public static <T> T or(T expect, T replace) {
        return expect == null ? replace : expect;
    }


    /**
     * 当expect为不为null， 使用handler重新map expect并返回map之后的值， 否则返回replace
     * demo : Null.or(expect, expect -> mapperToOtherObject(expect), replacement);
     */
    public static <T, R> R or(T expect, Function<T, R> mapper, R replace) {
        return expect == null ? replace : mapper.apply(expect);
    }

    /**
     * 当expect为不为null， 使用handler重新map expect并返回map之后的值， 否则返回null
     * demo : Null.or(expect, expect -> mapperToOtherObject(expect))
     */
    public static <T, R> R or(T expect, Function<T, R> mapper) {
        return or(expect, mapper, null);
    }

    /**
     * 集合中任意一条为null时返回true; 等价于 Arrays.asList(obj1, obj2, obj3).stream().any(Objects::isNull);
     * demo : boolean isContainNull = Null.any(expect1, expect2, expect3, expect4)
     */
    public static boolean any(Object... objs) {
        return Arrays.stream(objs).anyMatch(Objects::isNull);
    }

    /**
     * 全部为null时返回true
     */
    public static boolean all(Object... objs) {
        if (objs == null) {
            return true;
        }
        return Arrays.stream(objs).allMatch(Objects::isNull);
    }

    /**
     * 串行检测是否为null的入口
     *
     * @param obj 需要检测的对象
     */
    public static <T> Check<T> check(T obj) {
        return new Check<>(obj);
    }

    /**
     * 当前对象以及其map出来的所有子成员 任意为null时返回true;
     * 例子：
     * Null.any(obj, o->obj.item1, o->obj.item1.item1_1, o->obj.item1.item1_1.item1_1_1);
     * <p>
     * 当任意前置为null时，不会去执行后者。
     */
    @SafeVarargs
    public static <T> boolean any(T obj, Function<T, Object>... getters) {
        return obj == null || Arrays.stream(getters).anyMatch(o -> o.apply(obj) == null);
    }

    public static class Check<T> {
        public final T item;
        Check(T item) {
            this.item = item;
        }

        /**
         * 检测当前对象的成员
         *
         * @param mapper 获取成员的map
         */
        public <U> Check<U> check(Function<T, U> mapper) {
            return new Check<>(Null.or(item, mapper));
        }

        /**
         * 获得检测结果
         */
        public boolean check() {
            return item != null;
        }
    }
}

